# apps/menus/views.py
from django.http import HttpResponse
from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
from .models import Menu
from .serializers import MenuSerializer
import json

from ..audit.utils import log_action
from ..common.mixins import TenantViewSetMixin


class MenuViewSet(TenantViewSetMixin, viewsets.ModelViewSet):
    queryset = Menu.objects.all()
    serializer_class = MenuSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['is_active', 'menu_type', 'parent']
    # 仅管理员可管理菜单
    permission_classes = [permissions.IsAdminUser]

    @action(detail=False, methods=['get'], permission_classes=[permissions.IsAuthenticated])
    def user_menu(self, request):
        """
        获取当前用户有权访问的菜单树（仅菜单类型）
        """
        user = request.user
        # 获取用户有权限的所有菜单（包括父级菜单）
        menus = Menu.objects.filter(
            roles=user,
            is_active=True,
            menu_type='menu'
        ).distinct()

        # 递归构建完整菜单树（包含必要的父级）
        menu_ids = set()
        all_menus = set(menus)

        def add_ancestors(menu):
            parent = menu.parent
            while parent and parent.is_active:
                if parent not in all_menus:
                    all_menus.add(parent)
                parent = parent.parent

        for menu in menus:
            add_ancestors(menu)

        # 构建根菜单
        root_menus = [m for m in all_menus if m.parent is None]
        root_menus.sort(key=lambda x: x.order)

        serializer = MenuSerializer(root_menus, many=True)
        return Response(serializer.data)

    @action(detail=False, methods=['get'])
    def tree(self, request):
        """返回所有菜单的树形结构（用于配置界面）"""
        root_menus = Menu.objects.filter(parent=None).order_by('order')
        serializer = MenuSerializer(root_menus, many=True)
        return Response(serializer.data)

    @action(detail=True, methods=['post'])
    def move(self, request, pk=None):
        """拖拽排序接口"""
        menu = self.get_object()
        new_parent_id = request.data.get('parent_id')
        target_index = request.data.get('index')

        try:
            new_parent = Menu.objects.filter(id=new_parent_id).first() if new_parent_id else None
            menu.parent = new_parent
            menu.save()

            # 重新排序同级菜单
            siblings = Menu.objects.filter(parent=new_parent).order_by('order')
            menus = list(siblings)
            menus.remove(menu)
            menus.insert(target_index, menu)

            for idx, m in enumerate(menus):
                m.order = idx
                m.save()

            return Response({'status': 'ok'})
        except Exception as e:
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

    @action(detail=False, methods=['get'], permission_classes=[permissions.IsAdminUser])
    def export(self, request):
        """
        导出所有菜单为 JSON 文件
        """
        menus = Menu.objects.all().order_by('id')
        data = []
        for m in menus:
            item = {
                'title': m.title,
                'name': m.name,
                'path': m.path,
                'component': m.component,
                'icon': m.icon,
                'menu_type': m.menu_type,
                'parent_name': m.parent.name if m.parent else None,
                'order': m.order,
                'is_active': m.is_active,
                'is_external': m.is_external,
            }
            data.append(item)

        response = HttpResponse(
            json.dumps(data, ensure_ascii=False, indent=2),
            content_type='application/json'
        )
        response['Content-Disposition'] = 'attachment; filename="qb_menus.json"'
        return response

    @action(detail=False, methods=['post'], permission_classes=[permissions.IsAdminUser])
    def import_data(self, request):
        """
        从 JSON 文件导入菜单
        格式：[{title, name, path, component, icon, menu_type, parent_name, order, is_active}]
        """
        file_obj = request.FILES.get('file')
        if not file_obj:
            return Response({'error': '未上传文件'}, status=400)

        try:
            content = file_obj.read().decode('utf-8')
            data = json.loads(content)

            # 构建 name -> menu 映射
            menu_map = {}

            # ✅ 获取当前用户的租户
            tenant = TenantViewSetMixin.get_tenant_context(request)['tenant']

            for item in data:
                parent = None
                if item.get('parent_name'):
                    parent = menu_map.get(item['parent_name'])
                    if not parent:
                        # 尝试从数据库找（注意：也要过滤 tenant！）
                        parent_qs = Menu.objects.filter(name=item['parent_name'], tenant=tenant)
                        parent = parent_qs.first() if parent_qs.exists() else None

                # ✅ 在 defaults 中显式设置 tenant
                menu, created = Menu.objects.update_or_create(
                    name=item['name'],
                    defaults={
                        'title': item['title'],
                        'path': item['path'],
                        'component': item['component'],
                        'icon': item['icon'],
                        'menu_type': item['menu_type'],
                        'parent': parent,
                        'order': item['order'],
                        'is_active': item['is_active'],
                        'is_external': item['is_external'],
                        'tenant': tenant,  # ✅ 关键：显式指定租户
                    }
                )
                menu_map[item['name']] = menu

                # ✅ 记录审计日志
                if created:
                    action = 'create'
                    changes = None
                else:
                    action = 'update'
                    changes = {k: ['old', 'new'] for k, v in item.items() if getattr(menu, k) != v}
                log_action(
                    user=request.user,
                    action=action,
                    model_name='Menu',
                    object_id=menu.id,
                    object_repr=menu.title,
                    changes=changes,
                    request=request
                )

            return Response({'status': 'ok', 'imported': len(data)})

        except Exception as e:
            return Response({'error': str(e)}, status=400)

    @action(detail=False, methods=['get'], permission_classes=[permissions.IsAuthenticated])
    def routes(self, request):
        """
        返回所有菜单中 type=menu 且有 component 的路由
        格式兼容 vue-router
        """
        user = request.user
        menus = Menu.objects.filter(
            roles=user,
            is_active=True,
            menu_type='menu',
            component__isnull=False,
            component__gt=''  # 表示非空字符串
        ).distinct()

        def build_route(menu):
            route = {
                'name': menu.name,
                'path': menu.path,
                'component': menu.component,
                'meta': {
                    'title': menu.title,
                    'icon': menu.icon,
                    'permissions': [menu.name]  # 权限码
                }
            }
            children = menu.children.filter(
                is_active=True,
                menu_type='menu',
                component__isnull=False,
                component__gt=''  # 表示非空字符串
            )
            if children.exists():
                route['children'] = [build_route(child) for child in children]
            return route

        root_menus = menus.filter(parent=None)
        routes = [build_route(m) for m in root_menus]

        return Response(routes)

    def perform_create(self, serializer):

        # 关联当前用户的租户
        instance = serializer.save(tenant=self.request.user.tenant)

        log_action(
                user=self.request.user,
                action='create',
                model_name='Menu',
                object_id=instance.id,
                object_repr=instance.title,
                changes=None,
                request=self.request
        )

    def perform_update(self, serializer):
        # 关联当前用户的租户
        instance = serializer.save(tenant=self.request.user.tenant)
        # 记录变更字段
        changes = {}
        for field, value in serializer.validated_data.items():
            old_value = getattr(instance, field)
            if old_value != value:
                changes[field] = [str(old_value), str(value)]
        log_action(
            user=self.request.user,
            action='update',
            model_name='Menu',
            object_id=instance.id,
            object_repr=instance.title,
            changes=changes,
            request=self.request
        )

    def perform_destroy(self, instance):
        log_action(
            user=self.request.user,
            action='delete',
            model_name='Menu',
            object_id=instance.id,
            object_repr=instance.title,
            request=self.request
        )
        instance.delete()